home *** CD-ROM | disk | FTP | other *** search
/ Winzipper / Winzipper_ISO.iso / programming / oracle7 7.2 / DB / UTIL72 / DBMSPIPE.SQL < prev    next >
Encoding:
Text File  |  1995-05-09  |  19.9 KB  |  466 lines

  1. rem 
  2. rem $Header: dbmspipe.sql 7020100.1 94/09/23 22:14:38 cli Generic<base> $ 
  3. rem 
  4. Rem  Copyright (c) 1991 by Oracle Corporation 
  5. Rem    NAME
  6. Rem      dbmspipe.sql - send and receive from dbms "pipes"
  7. Rem    DESCRIPTION
  8. Rem      Allow sessions to pass information between them through 
  9. Rem      named SGA memory "pipes"
  10. Rem    RETURNS
  11. Rem 
  12. Rem    NOTES
  13. Rem      The procedural option is needed to use this facility.
  14. Rem      
  15. Rem    MODIFIED   (MM/DD/YY)
  16. Rem     ajasuja    06/21/94 -  change purge back to procedure
  17. Rem     ajasuja    06/09/94 -  secure pipes
  18. Rem     adowning   03/29/94 -  merge changes from branch 1.6.710.1
  19. Rem     adowning   02/02/94 -  split file into public / private binary files
  20. Rem     dsdaniel   07/09/93 -  dbms_defer longifaction for async rep
  21. Rem     rkooi      10/18/92 -  better comments 
  22. Rem     rkooi      08/20/92 -  comments and cleanup 
  23. Rem     rkooi      05/18/92 -  change comment 
  24. Rem     rkooi      04/28/92 -  change put to pack, etc. 
  25. Rem     rkooi      04/25/92 -  Creation 
  26.  
  27. REM ********************************************************************
  28. REM THIS PACKAGE MUST NOT BE MODIFIED BY THE CUSTOMER.  DOING SO
  29. REM COULD CAUSE INTERNAL ERRORS AND SECURITY VIOLATIONS IN THE
  30. REM RDBMS.  SPECIFICALLY, THE PSD ROUTINES IN KKXP MUST NOT BE CALLED
  31. REM DIRECTLY BY ANY CLIENT AND MUST REMAIN PRIVATE TO THE PACKAGE BODY.
  32. REM ********************************************************************
  33.  
  34. create or replace package dbms_pipe is
  35.  
  36.   ------------
  37.   --  OVERVIEW
  38.   --
  39.   --  This package provides a DBMS "pipe" service which allows messages
  40.   --  to be sent between sessions.
  41.   --
  42.   --  The metaphor is similar to UNIX pipes:  you can do
  43.   --      dbms_pipe.send_message(<pipename>)
  44.   --      dbms_pipe.receive_message(<pipename>)
  45.   --  which will cause a message to be sent or received.  You do
  46.   --      dbms_pipe.pack_message(<varchar2>|<number>|<date>)
  47.   --  to pack an item into a static buffer (which will then be sent with 
  48.   --  the "send_message" call), and
  49.   --      dbms_pipe.unpack_message(<varchar2>|<number>|<date>)
  50.   --  to get an item out of the static buffer (which is filled by the 
  51.   --  "receive_message" call).
  52.   --  Pipes can be private to a user-id - which only allows session connected
  53.   --  under the same user-id or stored procedure owned by the user-id to read
  54.   --  write to the pipe.  Pipes could be public - and all database users with
  55.   --  execute privilege on dbms_pipe and knowledge of the pipe can read or
  56.   --  write to the pipe.
  57.   --
  58.   --  Pipes operate independently of transactions.  They also operate
  59.   --  asynchronously.  There can be multiple readers and writers of the
  60.   --  same pipe.
  61.   --
  62.   --  Pipes only operate between sessions in the same instance.
  63.   --
  64.   --  Pipes can be explicitly created using
  65.   --    dbms_pipe.create_pipe(<pipename>)
  66.   --  and removed using 
  67.   --    dbms_pipe.remove_pipe(<pipename>)
  68.   --  A pipe created using the explicit create command should be removed
  69.   --  using the remove function.  A pipe can also be created implicitly.
  70.   --  Pipes automatically come into existence the first time they are
  71.   --  referenced.  They effectively disappear when they contain no more
  72.   --  data (some overhead remains in the SGA until it gets aged out).
  73.   --  Pipes take up space in the SGA (see "maxpipesize" parameter to 
  74.   --  "send_message").
  75.  
  76.  
  77.   --------
  78.   --  USES
  79.   --
  80.   --  The pipe functionality has several potential applications:
  81.   --
  82.   --    o External service interface.  You can provide the ability to
  83.   --      communicate with (user-written) services that are external to the
  84.   --      RDBMS.  This can be done in a (effectively) multi-threaded manner
  85.   --      so that several instances of the service can be executing
  86.   --      simultaneously. Additionally, the services are available
  87.   --      asynchronously - the requestor of the service need not block
  88.   --      awaiting a reply.  The requestor can check (with or without
  89.   --      timeout) at a later time.  The service can be written in any
  90.   --      of the 3GL languages that ORACLE supports, not just C.  See
  91.   --      example below.
  92.   --    o Independent transactions.  The pipe can be used to communicate
  93.   --      to a separate session which can perform an operation in an
  94.   --      independent transaction (such as logging an attempted security 
  95.   --      violation detected by a trigger).
  96.   --    o Alerters (non-transactional).  You can post another process
  97.   --      without requiring the waiting process to poll.  If an "after-row"
  98.   --      or "after-statement" trigger were to alert an application, then
  99.   --      the application would treat this alert as an indication that
  100.   --      the data probably changed.  The application would then go read
  101.   --      the data to get the current value.  Since this is an "after" 
  102.   --      trigger, the application would want to do a "select for update"
  103.   --      to make sure it read the correct data.
  104.   --    o Debugging.  Triggers and/or stored procedures can send debugging
  105.   --      information to a pipe.  Another session can keep reading out
  106.   --      of the pipe and displaying it on the screen or writing it 
  107.   --      out to a file.
  108.   --    o Concentrator. Useful for multiplexing large numbers of users
  109.   --      over a fewer number of network connections, or improving
  110.   --      performance by concentrating several user-transactions into
  111.   --      one dbms-transaction.
  112.  
  113.  
  114.   ------------
  115.   --  SECURITY
  116.   --
  117.   --  Security can be achieved by use of 'grant execute' on the dbms_pipe
  118.   --  package, by creating a pipe using the 'private' parameter in the create
  119.   --  function and by writing cover packages that only expose particular
  120.   --  features or pipenames to particular users or roles.
  121.  
  122.  
  123.   ------------
  124.   --  EXAMPLES
  125.   --
  126.   --  External service interface
  127.   ------------------------------
  128.   --
  129.   --  Put the user-written 3GL code into an OCI or Precompiler program.
  130.   --  The program connects to the database and executes PL/SQL code to read
  131.   --  its request from the pipe, computes the result, and then executes
  132.   --  PL/SQL code to send the result on a pipe back to the requestor.
  133.   --  Below is an example of a stock service request.
  134.   --  
  135.   --  The recommended sequence for the arguments to pass on the pipe
  136.   --  for all service requests is
  137.   --  
  138.   --      protocol_version    varchar2    - '1', 10 bytes or less
  139.   --      returnpipe        varchar2     - 30 bytes or less
  140.   --      service        varchar2     - 30 bytes or less
  141.   --      arg1            varchar2/number/date
  142.   --         ...
  143.   --      argn            varchar2/number/date
  144.   --  
  145.   --  The recommended format for returning the result is
  146.   --  
  147.   --      success        varchar2    - 'SUCCESS' if OK,
  148.   --                            otherwise error message
  149.   --      arg1            varchar2/number/date
  150.   --         ...
  151.   --      argn            varchar2/number/date
  152.   --  
  153.   --  
  154.   --  The "stock price request server" would do, using OCI or PRO* (in
  155.   --  pseudo-code):
  156.   --  
  157.   --    <loop forever>
  158.   --        begin dbms_stock_server.get_request(:stocksymbol); end;
  159.   --        <figure out price based on stocksymbol (probably from some radio
  160.   --          signal), set error if can't find such a stock>
  161.   --        begin dbms_stock_server.return_price(:error, :price); end;
  162.   --  
  163.   --  A client would do:
  164.   --
  165.   --      begin :price := stock_request('YOURCOMPANY'); end;
  166.   --      
  167.   --  The stored procedure, dbms_stock_server, which is called by the 
  168.   --  "stock price request server" above is:
  169.   --  
  170.   --    create or replace package dbms_stock_server is
  171.   --      procedure get_request(symbol out varchar2);
  172.   --      procedure return_price(errormsg in varchar2, price in varchar2);
  173.   --    end;
  174.   --  
  175.   --    create  or replace package body dbms_stock_server is
  176.   --      returnpipe    varchar2(30);
  177.   --  
  178.   --      procedure returnerror(reason varchar2) is
  179.   --        s integer;
  180.   --      begin
  181.   --        dbms_pipe.pack_message(reason);
  182.   --        s := dbms_pipe.send_message(returnpipe);
  183.   --        if s <> 0 then
  184.   --          raise_application_error(-20000, 'Error:' || to_char(s) ||
  185.   --            ' sending on pipe');
  186.   --        end if;
  187.   --      end;
  188.   --  
  189.   --      procedure get_request(symbol out varchar2) is
  190.   --        protocol_version varchar2(10);
  191.   --        s               integer;
  192.   --        service           varchar2(30);
  193.   --      begin
  194.   --        s := dbms_pipe.receive_message('stock_service');
  195.   --        if s <> 0 then
  196.   --          raise_application_error(-20000, 'Error:' || to_char(s) ||
  197.   --            'reading pipe');
  198.   --        end if;
  199.   --        dbms_pipe.unpack_message(protocol_version);
  200.   --        if protocol_version <> '1' then
  201.   --          raise_application_error(-20000, 'Bad protocol: ' || 
  202.   --            protocol_version);
  203.   --        end if;
  204.   --        dbms_pipe.unpack_message(returnpipe);
  205.   --        dbms_pipe.unpack_message(service);
  206.   --        if service != 'getprice' then
  207.   --          returnerror('Service ' || service || ' not supported');
  208.   --        end if;
  209.   --        dbms_pipe.unpack_message(symbol);
  210.   --      end;
  211.   --  
  212.   --      procedure return_price(errormsg in varchar2, price in varchar2) is
  213.   --        s integer;
  214.   --      begin
  215.   --        if errormsg is null then
  216.   --          dbms_pipe.pack_message('SUCCESS');
  217.   --          dbms_pipe.pack_message(price);
  218.   --        else
  219.   --          dbms_pipe.pack_message(errormsg);
  220.   --        end if;
  221.   --        s := dbms_pipe.send_message(returnpipe);
  222.   --        if s <> 0 then
  223.   --          raise_application_error(-20000, 'Error:'||to_char(s)||
  224.   --            ' sending on pipe');
  225.   --        end if;
  226.   --      end;
  227.   --    end;
  228.   --  
  229.   --  
  230.   --  The procedure called by the client is:
  231.   --  
  232.   --    create or replace function stock_request (symbol varchar2) 
  233.   --        return varchar2 is
  234.   --      s        integer;
  235.   --      price    varchar2(20);
  236.   --      errormsg varchar2(512);
  237.   --    begin
  238.   --      dbms_pipe.pack_message('1');  -- protocol version
  239.   --      dbms_pipe.pack_message(dbms_pipe.unique_session_name); -- return pipe
  240.   --      dbms_pipe.pack_message('getprice');
  241.   --      dbms_pipe.pack_message(symbol);
  242.   --      s := dbms_pipe.send_message('stock_service');
  243.   --      if s <> 0 then
  244.   --        raise_application_error(-20000, 'Error:'||to_char(s)||
  245.   --          ' sending on pipe');
  246.   --      end if;
  247.   --      s := dbms_pipe.receive_message(dbms_pipe.unique_session_name);
  248.   --      if s <> 0 then
  249.   --        raise_application_error(-20000, 'Error:'||to_char(s)||
  250.   --          ' receiving on pipe');
  251.   --      end if;
  252.   --      dbms_pipe.unpack_message(errormsg);
  253.   --      if errormsg <> 'SUCCESS' then
  254.   --        raise_application_error(-20000, errormsg);
  255.   --      end if;
  256.   --      dbms_pipe.unpack_message(price);
  257.   --      return price;
  258.   --    end;
  259.   --  
  260.   --  You would typically only grant execute on 'dbms_stock_service' to 
  261.   --  the stock service application server, and would only grant execute 
  262.   --  on 'stock_request' to those users allowed to use the service.
  263.  
  264.  
  265.   ---------------------
  266.   --  SPECIAL CONSTANTS
  267.   --
  268.   maxwait   constant integer := 86400000; /* 1000 days */ 
  269.   --  The maximum time to wait attempting to send or receive a message
  270.  
  271.  
  272.   ----------------------------
  273.   --  PROCEDURES AND FUNCTIONS
  274.   --
  275.   procedure pack_message(item in varchar2);
  276.   procedure pack_message(item in number);
  277.   procedure pack_message(item in date);
  278.   procedure pack_message_raw(item in raw);
  279.   procedure pack_message_rowid(item in rowid);
  280.   --  Pack an item into the message buffer
  281.   --  Input parameters:
  282.   --    item
  283.   --      Item to pack into the local message buffer.
  284.   --  Exceptions:
  285.   --    ORA-06558 generated if message buffer overflows (currently 4096
  286.   --    bytes).  Each item in the buffer takes one byte for the type,
  287.   --    two bytes for the length, plus the actual data.  There is also one
  288.   --    byte needed to terminate the message.
  289.   --
  290.   procedure unpack_message(item out varchar2);
  291.   procedure unpack_message(item out number);
  292.   procedure unpack_message(item out date);
  293.   procedure unpack_message_raw(item out raw);
  294.   procedure unpack_message_rowid(item out rowid);
  295.   --  Unpack an item from the local message buffer
  296.   --  Output parameters:
  297.   --    item
  298.   --      The argument to receive the next unpacked item from the local 
  299.   --      message buffer.
  300.   --  Exceptions:
  301.   --    ORA-06556 or 06559 are generated if the buffer contains
  302.   --    no more items, or if the item is not of the same type as that
  303.   --    requested (see 'next_item_type' below).
  304.   --
  305.   function next_item_type return integer;
  306.   --  Get the type of the next item in the local message buffer
  307.   --  Return value:
  308.   --    Type of next item in buffer:
  309.   --        0    no more items
  310.   --        9    varchar2
  311.   --        6    number
  312.   --       11    rowid
  313.   --       12    date
  314.   --       23    raw
  315.   --
  316.   function create_pipe(pipename in varchar2,
  317.                   maxpipesize in integer default 8192,
  318.                   private in boolean default TRUE)
  319.     return integer;
  320.   --  Create an empty pipe with the given name.
  321.   --  Input parameters:
  322.   --    pipename
  323.   --      Name of pipe to be created.  WARNING: Do not use pipe names
  324.   --      beginning with 'ORA$'.  These are reserved for use by procedures
  325.   --      provided by Oracle Corporation.  Pipename should not be longer than
  326.   --      128 bytes, and is case_insensitive.  At this time, the name cannot
  327.   --      contain NLS characters.
  328.   --    maxpipesize
  329.   --      Maximum allowed size for the pipe.  The total size of all the
  330.   --      messages on the pipe cannot exceed this amount.  The maxpipesize 
  331.   --      for a pipe becomes part of the pipe and persists for the lifetime
  332.   --      of the pipe.  Callers of send_message with larger values will 
  333.   --      cause the maxpipesize to be increased.  Callers with a smaller 
  334.   --      value will just use the larger value.  The specification of
  335.   --      maxpipesize here allows us to avoid its use in future send_message
  336.   --      calls.
  337.   --    private
  338.   --      Boolean indicating whether the pipe will be private - and for the
  339.   --      use of the creating user-id, or public.  A private pipe can be used
  340.   --      directly through calls to this package by sessions connected to the
  341.   --      database as the same user as the one that created the pipe.  It can
  342.   --      also be used via stored procedures owned by the user that created
  343.   --      the pipe.  The procedure may be executed by anyone with execute
  344.   --      privilege on it.  A public pipe can be accessed by anyone who has
  345.   --      knowledge of it and execute privilege on dbms_pipe.
  346.   --  Return values:
  347.   --    0 - Success.  This is returned even if the pipe had been created in
  348.   --        mode that permits its use by the user executing the create call.
  349.   --        If a pipe already existed, it is not emptied.
  350.   --  Exceptions:
  351.   --    Null pipe name.
  352.   --    Permission error.  Pipe with the same name already exists and
  353.   --      you are not allowed to use it.
  354.   --
  355.   function remove_pipe(pipename in varchar2)
  356.     return integer;
  357.   --  Remove the named pipe.
  358.   --  Input Parameters:
  359.   --    pipename
  360.   --      Name of pipe to remove.
  361.   --  Return value:
  362.   --    0 - Success. Calling remove on a pipe that does not exist returns 0.
  363.   --  Exceptions:
  364.   --    Null pipe name.
  365.   --    Permission error.  Insufficient privilege to remove pipe.  The
  366.   --      pipe was created and is owned by someone else.
  367.   --
  368.   function send_message(pipename in varchar2, 
  369.                         timeout in integer default maxwait,
  370.                         maxpipesize in integer default 8192)
  371.     return integer;
  372.   --  Send a message on the named pipe.  The message is contained in the
  373.   --    local message buffer which was filled with calls to 'pack_message'.
  374.   --    A pipe could have been created explicitly using 'create_pipe', or
  375.   --    it will be created implicitly.
  376.   --  Input parameters:
  377.   --    pipename
  378.   --      Name of pipe to place the message on.  The message is copied 
  379.   --      from the local buffer which can be filled by the "pack_message"
  380.   --      routine.  WARNING:  Do not use pipe names beginning with 'ORA$'.
  381.   --      These names are reserved for use by procedures provided by 
  382.   --      Oracle Corporation.  Pipename should not be longer than 128 bytes,
  383.   --      and is case_insensitive.  At this time, the name cannot
  384.   --      contain NLS characters.
  385.   --    timeout
  386.   --      Time to wait while attempting to place a message on a pipe, in
  387.   --      seconds (see return codes below).
  388.   --    maxpipesize
  389.   --      Maximum allowed size for the pipe.  The total size of all the
  390.   --      messages on the pipe cannot exceed this amount.  If this message 
  391.   --      would exceed this amount the call will block.  The maxpipesize 
  392.   --      for a pipe becomes part of the pipe and persists for the lifetime
  393.   --      of the pipe.  Callers of send_message with larger values will 
  394.   --      cause the maxpipesize to be increased.  Callers with a smaller 
  395.   --      value will just use the larger value.  The specification of
  396.   --      maxpipesize here allows us to avoid the use of a "open_pipe" call.
  397.   --  Return value:
  398.   --    0 - Success
  399.   --    1 - Timed out (either because can't get lock on pipe or    pipe stays 
  400.   --        too full)
  401.   --    3 - Interrupted
  402.   --  Exceptions:
  403.   --    Null pipe name.
  404.   --    Permission error.  Insufficient privilege to write to the pipe.
  405.   --      The pipe is private and owned by someone else.
  406.   function receive_message(pipename in varchar2,
  407.                            timeout in integer default maxwait)
  408.     return integer;
  409.   --  Receive a message from the named pipe.  Copy the message into the
  410.   --    local message buffer.  Use 'unpack_message' to access the
  411.   --    individual items in the message.  The pipe can be created explicitly
  412.   --    using the 'create_pipe' function or it will be created implicitly.
  413.   --  Input parameters:
  414.   --    pipename
  415.   --      Name of pipe from which to retrieve a message.  The message is 
  416.   --      copied into a local buffer which can be accessed by the 
  417.   --      "unpack_message" routine.  WARNING:  Do not use pipe names 
  418.   --      beginning with 'ORA$'.  These names are reserved for use by
  419.   --      procedures provided by Oracle Corporation. Pipename should not be
  420.   --      longer than 128 bytes, and is case-insensitive.  At this time,
  421.   --      the name cannot contain NLS characters.
  422.   --    timeout
  423.   --      Time to wait for a message.  A timeout of 0 allows you to read 
  424.   --      without blocking.  
  425.   --  Return value:
  426.   --    0 - Success
  427.   --    1 - Timed out
  428.   --    2 - Record in pipe too big for buffer (should not happen).
  429.   --    3 - Interrupted
  430.   --  Exceptions:
  431.   --    Null pipe name.
  432.   --    Permission error.  Insufficient privilege to remove the record
  433.   --      from the pipe.  The pipe is owned by someone else.
  434.   procedure reset_buffer;
  435.   --  Reset pack and unpack positioning indicators to 0.  Generally this
  436.   --    routine is not needed.
  437.   --
  438.   procedure purge(pipename in varchar2);
  439.   --  Empty out the named pipe.  An empty pipe is a candidate for LRU
  440.   --    removal from the SGA, therefore 'purge' can be used to free all
  441.   --    memory associated with a pipe.
  442.   --  Input Parameters:
  443.   --    pipename
  444.   --      Name of pipe from which to remove all messages.  The local 
  445.   --      buffer may be overwritten with messages as they are discarded.
  446.   --      Pipename should not be longer than 128 bytes, and is 
  447.   --      case-insensitive.
  448.   --  Exceptions:
  449.   --    Permission error if pipe belongs to another user.
  450.   --
  451.   function unique_session_name return varchar2;
  452.   --  Get a name that is unique among all sessions currently connected
  453.   --    to this database.  Multiple calls to this routine from the same 
  454.   --    session will always return the same value.
  455.   --  Return value:
  456.   --    A unique name.  The returned name can be up to 30 bytes.
  457.   --
  458. end;
  459. /
  460.  
  461. drop public synonym dbms_pipe
  462. /
  463. create public synonym dbms_pipe for sys.dbms_pipe
  464. /
  465.  
  466.